package router

import (
	"fmt"
	"log"
	"net/http"
	"scheduling/config"
	"scheduling/model"
	"scheduling/pool"
	"scheduling/task"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/jmoiron/sqlx"
)

var (
	db       *sqlx.DB
	conf     = config.GetConf()
	httpData = make(map[string]string, 0)
	done     = make(map[string]chan int, 0)
	timed    = make(map[string]string, 0)
	perms    = make(map[string]model.SignKeys, 0)
)

func init() {
	var err error
	db, err = pool.NewDBConnect(conf.Driver.Name, conf.Driver.Url, 2, 5)
	if err != nil {
		log.Fatal(err)
	}
	runHttp()
	runTimed()
	runTcpServer()
	nacosInit()
	ticker := time.NewTicker(time.Minute * 10)
	go func() {
		for _ = range ticker.C {
			runHttp()
			runTimed()
			loadKeysInit()
		}
	}()
}

//加载密钥数据
func loadKeysInit() {
	sql := `select * from sign_keys`
	data := make([]model.SignKeys, 0)
	err := db.Select(&data, sql)
	if err != nil {
		log.Println("查询密钥数据失败！", err)
		return
	}
	for _, v := range data {
		perms[v.Pid.String] = v
	}
}

//加载Nacos服务配置
func nacosInit() {
	sql := `select * from nacos_configs`
	configs := make([]model.NacosConfigs, 0)
	err := db.Select(&configs, sql)
	if err != nil {
		log.Println("查询Nacos服务配置失败！", err)
		return
	}
	sql = `select * from nacos_services`
	services := make([]model.NacosServices, 0)
	err = db.Select(&services, sql)
	if err != nil {
		log.Println("查询Nacos服务器失败！", err)
		return
	}
	for _, c := range configs {
		serves := make([]model.NacosServices, 0)
		for _, s := range services {
			if c.Pid == s.ConfigId {
				serves = append(serves, s)
			}
		}
		ns := task.NewNacosCloud(c, serves)
		ns.Start()
	}
}

//加载定时任务
func runTimed() {
	sql := `select * from cf_flows where flow_type='TIMED' and flow_state='1'`
	result := make([]model.CfFlows, 0)
	err := db.Select(&result, sql)
	if err != nil {
		log.Println("查询流程缓存数据出错！", err)
		return
	}
	timed = make(map[string]string, 0)
	for _, v := range result {
		if timed[v.Pid.String] == v.FlowData.String {
			continue
		}
		c := done[v.Pid.String]
		if c == nil {
			c = make(chan int)
		} else {
			c <- 1
		}
		go task.TimedStart(c, v.FlowData.String)
		done[v.Pid.String] = c
		timed[v.Pid.String] = v.FlowData.String
	}
}

//加载HTTP数据
func runHttp() {
	sql := `select * from cf_flows where flow_type='HTTP' and flow_state='1'`
	result := make([]model.CfFlows, 0)
	err := db.Select(&result, sql)
	if err != nil {
		log.Println("查询流程缓存数据出错！", err)
		return
	}
	httpData = make(map[string]string, 0)
	for _, v := range result {
		httpData[v.Pid.String] = v.FlowData.String
	}
}

//加载TCPServer数据
func runTcpServer() {
	sql := `select * from cf_flows where flow_type='TCP_SERVER' and flow_state='1'`
	result := make([]model.CfFlows, 0)
	err := db.Select(&result, sql)
	if err != nil {
		log.Println("查询流程缓存数据出错！", err)
		return
	}
	for _, v := range result {
		serve, err := task.NewTcpServer(v.FlowData.String)
		if err != nil {
			panic(err)
		}
		go serve.Start()
	}
}

func NewRouter() error {
	router := gin.Default()
	router.Use(Cors())

	router.POST("/:flowId", index)

	handler := task.NewWebSocketHandler(httpData)
	router.GET("/ws", func(c *gin.Context) {
		handler.Connect(c)
	})
	err := router.Run(":" + conf.Server.Port)
	if err != nil {
		fmt.Println(err)
	}

	return err
}

func index(c *gin.Context) {
	flowId := c.Param("flowId")
	flowData := httpData[flowId]
	if flowData == "" {
		c.JSON(http.StatusOK, "未找到流程配置信息")
		return
	}

	t, err := task.NewFlowTask(c, flowData)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": "1003", "msg": err.Error()})
		return
	}
	t.Start(perms)
}

//跨域处理
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		origin := c.Request.Header.Get("Origin")
		var headerKeys []string
		for k, _ := range c.Request.Header {
			headerKeys = append(headerKeys, k)
		}
		headerStr := strings.Join(headerKeys, ", ")
		if headerStr != "" {
			headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr)
		} else {
			headerStr = "access-control-allow-origin, access-control-allow-headers"
		}
		if origin != "" {
			c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析
			c.Header("Access-Control-Max-Age", "172800")                                                                                                                                                           // 缓存请求信息 单位为秒
			c.Header("Access-Control-Allow-Credentials", "false")                                                                                                                                                  //  跨域请求是否需要带cookie信息 默认设置为true
			c.Set("content-type", "application/json")                                                                                                                                                              // 设置返回格式是json
		}

		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "Options Request!")
		}
		// 处理请求
		c.Next() //  处理请求
	}
}
